#include "MagicCube.h"
MagicCube::MagicCube(scene::ISceneNode* parent, scene::ISceneManager* smgr, s32 id, f32 len, IrrlichtDevice *dev)
: manager(smgr), device(dev), length(len)
{
	// parent
	Center = new Cube(parent, smgr, IDFlag_MIDDLE | IDFlag_MIDDLE | IDFlag_MIDDLE, length);
	for (int i = 0; i < 3; i++) // y
	{
		int y = IDFlag_MIDDLE;
		if (i == 0) y = IDFlag_BOTTOM;
		if (i == 2) y = IDFlag_TOP;
		for (int j = 0; j < 3; j++) // z 
		{
			int z = IDFlag_MIDDLE;
			if (j == 0) z = IDFlag_FRONT;
			if (j == 2) z = IDFlag_BACK;
			for (int k = 0; k < 3; k++) // x
			{
				int x = IDFlag_MIDDLE;
				if (k == 0) x = IDFlag_LEFT;
				if (k == 2) x = IDFlag_RIGHT;
				cubes[i * 9 + j * 3 + k] = new Cube(Center, smgr, x | y | z, length);
				cubes[i * 9 + j * 3 + k]->setPosition(vector3df((k - 1) * length , (i - 1) * length, (j - 1) * length));
			}
		}
	}
}
MagicCube::~MagicCube()
{
	Center = 0;
	for (int i = 0; i < 27; i++)
	{
		delete cubes[i];
		cubes[i] = 0;
	}
	manager = 0;
}

bool MagicCube::hasStop()
{
	for (int i = 0; i < 27 ;i++)
		if (!cubes[i]->hasStop())
			return false;
	return true;
}

void MagicCube::reSet()
{
	for (int i = 0; i < 27; i++)
		cubes[i]->setParent(Center);
	cubes[13]->setRotation(core::vector3df(0,0,0));
	cubes[13]->updateAbsolutePosition();
}

void MagicCube::chooseThisCube(int id)
{
	for (int i = 0; i < 27; i++)
		if (cubes[i]->getID() == id)
		{
			cubes[i]->setPosition(cubes[i]->getPosition() * 1.05);
			cubes[i]->updateAbsolutePosition();
		}
}

void MagicCube::resetThisCube(int id)
{
	for (int i = 0; i < 27; i++)
		if (cubes[i]->getID() == id)
		{
			cubes[i]->setPosition(cubes[i]->getPosition() / 1.05);
			cubes[i]->updateAbsolutePosition();
		}
}

void MagicCube::setSelector()
{
	for (int i = 0; i < 27; i++)
	{
		scene::ITriangleSelector* select = manager->createTriangleSelectorFromBoundingBox(cubes[i]);
		cubes[i]->setTriangleSelector(select);
		select->drop();
	}
}

void MagicCube::rotate(core::vector3df pos, core::vector3df normal)
{
	core::vector3df Rotate(0,0,0);
	if (core::abs_(normal.X) > core::abs_(normal.Y))
		if (core::abs_(normal.X) > core::abs_(normal.Z))
			Rotate.X = 1;
		else
			Rotate.Z = 1;
	else
		if (core::abs_(normal.Y) > core::abs_(normal.Z))
			Rotate.Y = 1;
		else
			Rotate.Z = 1;
	f32 inverse = Rotate.dotProduct(normal) > 0 ? 1 : -1;

	reSet();
	f32 standard = pos.dotProduct(Rotate);
	for (int i = 0; i < 27 ;i++)
	{
		if (i == 13) continue;
		if (core::abs_(Rotate.dotProduct(cubes[i]->getAbsolutePosition()) - standard) < length / 3)
			cubes[i]->setParent(cubes[13]);		
	}
	scene::Rotation90BaseParent* anim = new
		Rotation90BaseParent(device->getTimer()->getTime(), Rotate * inverse);
	if(anim)
	{
		cubes[13]->addAnimator(anim);
		anim->drop();
		anim = 0;
	} 
}

void MagicCube::setCollisionNode(ISceneNode* node)
{
	for (int i = 0; i < 27 ;i++)
	{
		scene::ISceneNodeAnimator* anim = manager->createCollisionResponseAnimator(
			cubes[i]->getTriangleSelector(), node, core::vector3df(10,10,10), core::vector3df(0,0,0));
		node->addAnimator(anim);
		anim->drop();
	}
}

void MagicCube::homing()
{
	for (int i = 0; i < 27 ;i++)
	{
		int id = cubes[i]->getID();
		int x = bool(id & IDFlag_RIGHT) - bool(id & IDFlag_LEFT);
		int y = bool(id & IDFlag_TOP) - bool(id & IDFlag_BOTTOM);
		int z = bool(id & IDFlag_BACK) - bool(id & IDFlag_FRONT);
		cubes[i]->setPosition(vector3df(x * length , y * length, z * length));
		cubes[i]->setRotation(vector3df(0,0,0));
		cubes[i]->updateAbsolutePosition();
	}
}
bool MagicCube::check()
{
	for (int i = 0; i < 27; i++)
	{
		int id = cubes[i]->getID();
		int x = bool(id & IDFlag_RIGHT) - bool(id & IDFlag_LEFT);
		int y = bool(id & IDFlag_TOP) - bool(id & IDFlag_BOTTOM);
		int z = bool(id & IDFlag_BACK) - bool(id & IDFlag_FRONT);
		core::vector3df pos = cubes[i]->getAbsolutePosition();
		pos /= length; 
		if (core::abs_(pos.X - x) > 0.5)
			return false;
		if (core::abs_(pos.Y - y) > 0.5)
			return false;
		if (core::abs_(pos.Z - z) > 0.5)
			return false;
	}
	return true;
}